<template>
  <n-form
    ref="formRef"
    require-mark-placement="left"
    label-placement="left"
    inline
    :label-width="100"
    :model="model"
    show-feedback
    :rules="rules"
  >
    <n-grid :cols="24">
      <n-form-item-gi
        v-for="item in props.list"
        :key="item.key"
        :span="item.span ? item.span : props.span"
        :path="String(item.key)"
      >
        <template #label>
          <span>{{ item.label }}</span>
        </template>
        <template #default>
          <component :is="getFieldComponent(item)" style="width: 100%" />
          <n-popover v-if="item.labelTips" trigger="hover">
            <template #trigger>
              <n-icon size="14" :component="HelpCircleSharp" />
            </template>
            <span>{{ item.labelTips }}</span>
          </n-popover>
        </template>
      </n-form-item-gi>
      <n-gi :span="24">
        <n-space justify="end">
          <n-button round type="primary" @click="handleCancel">
            {{ $t(props.cancelText) }}
          </n-button>
          <n-button round type="primary" @click="handleSubmit">
            {{ $t(props.submitText) }}
          </n-button>
        </n-space>
      </n-gi>
    </n-grid>
  </n-form>
</template>

<script setup lang="ts" generic="F extends { [x: string]: any }, M extends Partial<Record<keyof F, any>>">
import { HelpCircleSharp } from '@vicons/ionicons5'
import { NDatePicker, NInput, NInputNumber, NRadio, NRadioGroup, NSelect, NTree, NTreeSelect } from 'naive-ui'
import type { FormInst, FormRules, TreeOption } from 'naive-ui'
import { useI18n } from 'vue-i18n'

import { FormInputList } from '@/types/interface'

interface Props {
  list: FormInputList<F>
  model: M
  rules?: FormRules
  submitText?: string
  cancelText?: string
  span?: number
}

const props = withDefaults(defineProps<Props>(), {
  span: 6,
  submitText: 'common.submit',
  cancelText: 'common.cancel',
  rules: undefined,
})

const emit = defineEmits<{
  (e: 'handle-cancel'): void
  (e: 'handle-submit'): void
}>()

const { t } = useI18n()
const formRef = ref<FormInst | null>(null)

const getFieldComponent = (field: Record<string, any>) => {
  const commonProps = {
    'value': props.model[field.key],
    'onUpdate:value': (value: any) => (props.model[field.key] = value),
    'clearable': true,
  }
  switch (field.type) {
    case 'input':
      return h(NInput, commonProps)
    case 'input-number':
      return h(NInputNumber, {
        ...commonProps,
        min: field.min,
        max: field.max,
      })
    case 'textarea':
      return h(NInput, {
        ...commonProps,
        type: 'textarea',
      })
    case 'select':
      return h(NSelect, { ...commonProps, options: field.options, multiple: field.multiple })
    case 'date-picker':
      return h(NDatePicker, { ...commonProps, type: 'daterange' })
    case 'tree':
      return h(NTree, {
        clearable: false,
        checkedKeys: props.model[field.key]?.checkedKeys,
        onUpdateCheckedKeys: (value: any) => {
          props.model[field.key] = { ...props.model[field.key], checkedKeys: value }
        },
        indeterminateKeys: props.model[field.key]?.halfCheckedKeys,
        onUpdateIndeterminateKeys: (value: any) => {
          props.model[field.key] = { ...props.model[field.key], halfCheckedKeys: value }
        },
        blockLine: true, // 连线
        virtualScroll: true, // 显示滚动条
        trigger: 'none', // 滚动条显示触发方式
        style: 'height: 150px',
        checkable: true, // 是否显示选择框
        cascade: true, // 是否级联选择
        defaultExpandAll: true, // 是否默认展开所有节点
        data: field.data, // 树形数据
        keyField: field.keyField || 'key', // 树形数据中的key字段
        labelField: field.labelField || 'label', // 树形数据中的label字段
        childrenField: field.childrenField || 'children', // 树形数据中的children字段
        showLine: true, // 是否显示树形结构连线
        expandOnClick: true, // 点击节点时是否展开/折叠节点
        renderLabel: ({ option }: { option: TreeOption }) => {
          const label = option.label ?? ''
          return t(label)
        },
      })

    case 'radio':
      return h(
        NRadioGroup,
        { ...commonProps },
        {
          default: () =>
            field.options.map((song: any) => h(NRadio, { key: song.value, value: song.value }, () => song.label)),
        },
      )

    case 'tree-select':
      return h(NTreeSelect, {
        ...commonProps,
        options: field.options,
        multiple: field.multiple,
        defaultExpandAll: true,
        keyField: field.keyField || 'key', // 树形数据中的key字段
        labelField: field.labelField || 'label', // 树形数据中的label字段
        childrenField: field.childrenField || 'children', // 树形数据中的children字段
      })
    default:
  }
}

const handleCancel = () => {
  emit('handle-cancel')
}

const handleSubmit = () => {
  formRef.value?.validate((errors) => {
    if (errors) return

    emit('handle-submit')
  })
}
</script>

<style scoped lang="less">
/* 样式可以根据需要进行调整 */
</style>
